﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ADDDF.Infrastructure
{
    public class EventManager
    {
        #region HandlerInfo

        class HandlerInfo
        {
            public EventHandlerDelegate Handler { get; set; }
            public object Data { get; set; }
        }
        
        #endregion

        #region Fields

        private Dictionary<string, List<HandlerInfo>> _eventToHandlers;

        #endregion

        public EventManager()
        {
            _eventToHandlers = new Dictionary<string, List<HandlerInfo>>();
        }

        public void Bind(IEvent anEvent, EventHandlerDelegate handler, object data)
        {            
            string eventName = anEvent.GetType().FullName;

            if (!_eventToHandlers.ContainsKey(eventName))
            {
                _eventToHandlers.Add(eventName, new List<HandlerInfo>());
            }

            List<HandlerInfo> handlers = _eventToHandlers[eventName];

            HandlerInfo handlerInfo = handlers.SingleOrDefault(x => x.Handler.Equals(handler));

            if (handlerInfo == null)
            {
                handlers.Add(new HandlerInfo { Handler = handler, Data = data });
            }
            else
            {
                handlerInfo.Data = data;
            }
        }

        public void Unbind(IEvent anEvent, EventHandlerDelegate handler)
        {
            string eventName = anEvent.GetType().FullName;

            if (!_eventToHandlers.ContainsKey(eventName))
            {
                return;
            }

            List<HandlerInfo> handlers = _eventToHandlers[eventName];

            HandlerInfo handlerInfo = handlers.SingleOrDefault(x => x.Handler.Equals(handler));

            if (handlerInfo == null)
            {
                return;
            }
            else
            {
                handlers.Remove(handlerInfo);
            }
        }

        public void Trigger(IEvent anEvent, EventArgs args)
        {
            string eventName = anEvent.GetType().FullName;

            if (!_eventToHandlers.ContainsKey(eventName))
            {
                return;
            }

            List<HandlerInfo> handlers = _eventToHandlers[eventName];

            foreach (HandlerInfo handlerInfo in handlers)
            {
                handlerInfo.Handler.Invoke(anEvent, args, handlerInfo.Data);
            }
        }

        #region Singleton Implementation

        public static EventManager Instance = new EventManager();

        #endregion
    }
}
